package com.linhs.payment.controller;

import com.google.gson.Gson;
import com.linhs.payment.service.WxPayService;
import com.linhs.payment.util.HttpUtils;
import com.linhs.payment.util.WechatPay2ValidatorForRequest;
import com.linhs.payment.vo.R;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author linhs
 * @menu
 * @Title:
 * @Package
 * @Description:
 * @date 2023/7/27 15:47
 */
@CrossOrigin
@RestController
@RequestMapping("/api/wx-pay")
@Api(tags = "网站微信API")
@Slf4j
public class WxPayController {

    @Resource
    private WxPayService wxPayService;
    @Resource
    private Verifier verifier;

    /**
     * Native下单
     *
     * @param productId
     * @return
     * @throws Exception
     */
    @ApiOperation("调用统一下单API，生成支付二维码")
    @PostMapping("/native/{productId}")
    public R nativePay(@PathVariable Long productId) throws Exception {

        log.info("发起支付请求 v3");

        //返回支付二维码连接和订单号
        Map<String, Object> map = wxPayService.nativePay(productId);

        return R.ok().setData(map);
    }


    /**
     * {
     * "id":"349c8b1b-9da5-5ce1-917e-10db5db10b9c",
     * "create_time":"2023-08-01T11:06:14+08:00",
     * "resource_type":"encrypt-resource",
     * "event_type":"TRANSACTION.SUCCESS",
     * "summary":"支付成功",
     * "resource":{
     *      "original_type":"transaction",
     *      "algorithm":"AEAD_AES_256_GCM",
     *      "ciphertext":"ew9Fm94yxZNk2TAzdy8Z12cczg5eHY32uzufrsdgZXrsZiN9R90s0y9Q/aLpE2cVOAnvsEIjE6PaP8isdzHbL7g6Fv9vfr5M2l/p7YgEa2/6jP9pCN8YOEfsO4dAdIsS/ezATFGJPhuSBdD9/VsVUp6iH/fp06kuWEZnCgxwf17X9gmvAIZRbsndgU3Ww+q0FZHph3ho680pia4Q0nfbu6EUTzWFiZ0DOXAnh7Qm7pkgCIP/fF4T8sfNC0I/ZlwmBVTG1tcLQW29WxalvU4wmGTrGqVbOCgxLJii2SZJQafT4vggkHpDmxeDs6Tqr9tmDvhYYhStbTrRs4b29tiOAHv1AXwUF5K9Ua60aWf1uCtCAhjRTDfEM2On5sCWX+7XAXogJ47uUxyXKgrVHZmTGc73erBf7r6mb2xMmVmrPZ2kZPP5fC0fJTiy2EFs5iucbHGfk43kaRtBpcFek6iXZTTCY154anQPGyK0nGqM75C6Ky2TGhuQSqRz1+XgoTS3ldUzELTJXGKf/JNyWsKz2ifW8tS6FJUjeFYHJGK76+oAzd/+kq0jVQgGY5+L1StGUKSgmobG1Q==",
     *      "associated_data":"transaction",
     *      "nonce":"69BpYnI77NRN"
     *  }
     * }
     * <p>
     * <p>
     * <p>
     * 支付通知
     * 微信支付通过支付通知接口将用户支付成功消息通知给商户
     */
    @ApiOperation("支付通知")
    @PostMapping("/native/notify")
    public String nativeNotify(HttpServletRequest request, HttpServletResponse response) {

        Gson gson = new Gson();
        Map<String, String> returnMap = new HashMap<>();//应答对象
        try {
            //处理通知参数
            String body = HttpUtils.readData(request);
            Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);

            String requestId = (String) bodyMap.get("id");
            log.info("支付通知的id ===> {}", requestId);
            log.info("支付通知的完整数据 ===> {}", body);
            //int a = 9 / 0;

            //签名的验证
            WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(verifier, requestId, body);
            if (!wechatPay2ValidatorForRequest.validate(request)) {
                log.error("通知验签失败");
                //失败应答
                response.setStatus(500);
                returnMap.put("code", "ERROR");
                returnMap.put("message", "通知验签失败");
                return gson.toJson(returnMap);
            }
            log.info("通知验签成功");

            //处理订单
            wxPayService.processOrder(bodyMap);

            //应答超时
            //模拟接收微信端的重复通知
//            TimeUnit.SECONDS.sleep(5);

            //成功应答
            response.setStatus(200);
            returnMap.put("code", "SUCCESS");
            returnMap.put("message", "成功");
            return gson.toJson(returnMap);

        } catch (Exception e) {
            e.printStackTrace();
            //失败应答
            response.setStatus(500);
            returnMap.put("code", "ERROR");
            returnMap.put("message", "失败");

            return gson.toJson(returnMap);
        }

    }


    /**
     * 查询订单
     *
     * @param orderNo
     * @return
     * @throws Exception
     */
    @ApiOperation("查询订单：测试订单状态用")
    @GetMapping("/query/{orderNo}")
    public R queryOrder(@PathVariable String orderNo) throws Exception {

        log.info("查询订单");
        String result = wxPayService.queryOrder(orderNo);
        return R.ok().setMsg("查询成功").data("result", result);

    }


    /**
     * 用户取消订单
     *
     * @param orderNo
     * @return
     * @throws Exception
     */
    @ApiOperation("用户取消订单")
    @PostMapping("/cancel/{orderNo}")
    public R cancel(@PathVariable String orderNo) throws Exception {

        log.info("取消订单");

        wxPayService.cancelOrder(orderNo);
        return R.ok().setMsg("订单已取消");
    }

    @ApiOperation("申请退款")
    @PostMapping("/refunds/{orderNo}/{reason}")
    public R refunds(@PathVariable String orderNo, @PathVariable String reason) throws Exception {

        log.info("申请退款");
        wxPayService.refund(orderNo, reason);
        return R.ok();
    }

    /**
     * 查询退款
     *
     * @param refundNo
     * @return
     * @throws Exception
     */
    @ApiOperation("查询退款：测试用")
    @GetMapping("/query-refund/{refundNo}")
    public R queryRefund(@PathVariable String refundNo) throws Exception {

        log.info("查询退款");

        String result = wxPayService.queryRefund(refundNo);
        return R.ok().setMsg("查询成功").data("result", result);
    }

    /**
     * 退款结果通知
     * 退款状态改变后，微信会把相关退款结果发送给商户。
     */
    @ApiOperation("退款结果通知")
    @PostMapping("/refunds/notify")
    public String refundsNotify(HttpServletRequest request, HttpServletResponse response) {

        log.info("退款通知执行");
        Gson gson = new Gson();
        Map<String, String> map = new HashMap<>();//应答对象

        try {
            //处理通知参数
            String body = HttpUtils.readData(request);
            Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
            String requestId = (String) bodyMap.get("id");
            log.info("支付通知的id ===> {}", requestId);

            //签名的验证
            WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(verifier, requestId, body);
            if (!wechatPay2ValidatorForRequest.validate(request)) {

                log.error("通知验签失败");
                //失败应答
                response.setStatus(500);
                map.put("code", "ERROR");
                map.put("message", "通知验签失败");
                return gson.toJson(map);
            }
            log.info("通知验签成功");

            //处理退款单
            wxPayService.processRefund(bodyMap);

            //成功应答
            response.setStatus(200);
            map.put("code", "SUCCESS");
            map.put("message", "成功");
            return gson.toJson(map);

        } catch (Exception e) {
            e.printStackTrace();
            //失败应答
            response.setStatus(500);
            map.put("code", "ERROR");
            map.put("message", "失败");
            return gson.toJson(map);
        }
    }

}
